﻿#ifndef __GAF_MEMMANAGE_H__
#define __GAF_MEMMANAGE_H__


// #undef GAF_SAFE_MEMORY

#include "GAF_Define.h"
#include "GAF_MemHand.h"

#pragma WARNING(disable:4345)

#ifdef GAF_SAFE_MEMORY

#ifndef BYTE
typedef unsigned char			BYTE;
#endif

#define GAF_THEMEMMANAGE		GAF::MemManage::GetInstance()

#define _NEW_MEMHAND(_TYPE, _Param, _nCount) \
	(_nCount <= 0) ? NULL : \
	new GAF::MemHand<_TYPE>( \
		new((BYTE*)_MALLOC(sizeof(GAF::MemInfo) + sizeof(_TYPE) * (_nCount)) + sizeof(GAF::MemInfo)) _TYPE _Param, _nCount)

#ifdef GAF_DEBUG
#define _NEW_ANY(_TYPE, _Param, _nCount, _MemType) \
	(_TYPE*)GAF_THEMEMMANAGE.New( \
		_NEW_MEMHAND(_TYPE, _Param, _nCount), \
		sizeof(_TYPE) * (_nCount), _nCount, _MemType, #_TYPE, __FILE__, __LINE__)
#else /*GAF_DEBUG*/
#define _NEW_ANY(_TYPE, _Param, _nConut, _MemType) \
	(_TYPE*)GAF::g_MemManage.New( \
		_NEW_MEMHAND(_TYPE, _Param, _nCount), \
		sizeof(_TYPE) * (_nCount), _nConut, _MemType)
#endif /*GAF_DEBUG*/

/// 申请实例内存，无参数
#define GAF_NEW(_TYPE)			_NEW_ANY(_TYPE, (), 1, GAF::MEM_ONE)
/// 申请实例内存，有参数
#define GAF_NEW_PRM(_TYPE, _Param)	_NEW_ANY(_TYPE, _Param, 1, GAF::MEM_ONE)
/// 申请实例数组内存
#define GAF_NEW_ARY(_TYPE, _nCount)	_NEW_ANY(_TYPE, (), _nCount, GAF::MEM_ARY)

/// 释放实例内存
// 如果内存释放失败，请检查申请此内存时是否处理妥当。
#define GAF_DELETE(_p)			if(_p != NULL){if(GAF_THEMEMMANAGE.Delete(_p, GAF::MEM_ONE)) _p = NULL;}
#define GAF_DELETE_ARY(_p)		if(_p != NULL){if(GAF_THEMEMMANAGE.Delete(_p, GAF::MEM_ARY)) _p = NULL;}

/// 内存回收
#define GAF_MEM_GC()
/// 释放所有内存
#define GAF_MEM_RELEASE()		GAF_THEMEMMANAGE.DeleteAll()
/// 获得占用内存大小
#define GAF_MEM_SIZE()			GAF_THEMEMMANAGE.GetMemSize()
/// 获得申请的实例数量
#define GAF_MEM_COUNT()			GAF_THEMEMMANAGE.GetHandCount()

#else /*GAF_SAFE_MEMORY*/
#define GAF_NEW(_TYPE)			new _TYPE()
#define GAF_NEW_PRM(_TYPE, _Param)	new _TYPE _Param
#define GAF_NEW_ARY(_TYPE, _nCount)	new _TYPE[_nCount]
#define GAF_DELETE(_p)			if(_p != NULL){delete _p; _p = NULL;}
#define GAF_DELETE_ARY(_p)		if(_p != NULL){delete[] _p; _p = NULL;}

#define GAF_MEM_GC()
#define GAF_MEM_RELEASE()
#define GAF_MEM_SIZE()			0
#define GAF_MEM_COUNT()			0

#endif /*GAF_SAFE_MEMORY*/


/*
	       Head
	        V
	+---------------------------------------+
	|    头信息	|    对象内存		|
	+---------------------------------------+
	       V A
	+---------------------------------------+
	|    头信息	|    对象内存		|
	+---------------------------------------+
	       V A
	+---------------------------------------+
	|    头信息	|    对象内存		|
	+---------------------------------------+
	        A
	       End

	<1>		<-
	+---------------------------------------+
	|  <4> 头信息	|  <2> 对象内存		|
	+---------------------------------------+
		    V       A
		+---------------+
		| <3> 地址存储	|
		+---------------+
*/


namespace GAF
{
#ifdef GAF_SAFE_MEMORY
#define GAF_MEM_VALIDATE			1234567890

	// 申请内存的类型(单体，数组，不详)
	enum MemType
	{
		MEM_ONE,
		MEM_ARY,
		MEM_UNKNOW,
	};

	class MemManage;

	/// 实例内存信息结构
	struct MemInfo
	{
		/// 验证值
		long			nValidate;
		/// 创建者
		MemManage*		pCreater;

		/// 地址指针
		BaseHand*		pHand;
		/// 内存大小
		size_t			nSize;
		/// 内存类型
		MemType			mt;

		/// 链表上一个
		MemInfo*		pPrev;
		/// 链表下一个
		MemInfo*		pNext;

#ifdef GAF_DEBUG
		/// 唯一标记递增序号
		unsigned int		nMarkID;
		/// 申请数量
		unsigned int		nCount;
		/// 类名
		_STRING			strClassName;
		/// 声明文件
		_STRING			strFile;
		/// 声明位置
		int			nLine;
#endif /*GAF_DEBUG*/
	};

	/**
 	 *  @addtogroup Memory
	 *  @{
	 */
	/// 内存管理类
	class MemManage
	{
#ifdef GAF_DEBUG
		typedef unsigned int		MemInfoMapKey;
		typedef std::map<MemInfoMapKey, MemInfo*>
						MemInfoMap;
#endif /*GAF_DEBUG*/

	public:
		static MemManage&		GetInstance();

	private:
		MemManage();
		~MemManage();

	public:

#ifdef GAF_DEBUG
		/// 申请实例内存
		void*				New(BaseHand* pMemHand, size_t nMemSize, unsigned int nAryCount, MemType mt, _STRING strClass = "", const _STRING strFile = "", int nLine = 0);
#else
		void*				New(BaseHand* pMemHand, size_t nMemSize, unsigned int nAryCount, MemType mt);
#endif /*GAF_DEBUG*/

		/// 释放指定地址内存
		bool				Delete(void* pointer, MemType mt);
		/// 释放所有内存
		void				DeleteAll();
		/// 获得所有内存空间
		int				GetMemSize();
		/// 获得句柄数量
		int				GetHandCount();

	private:
		unsigned int			m_nTotalSize;
		unsigned int			m_nCount;

#ifdef GAF_DEBUG
		unsigned int			m_nIDMark;
		MemInfoMap			m_MemInfoMap;
#endif /*GAF_DEBUG*/

		MemInfo*			m_pHead;
		MemInfo*			m_pEnd;
	};

	extern 	MemManage			g_MemManage;
#endif /*GAF_SAFE_MEMORY*/

	/** @} */

}

#endif
